// 封装axios请求模块
import axios from 'axios';
// 在非组件模块中获取 store必须通过这种方式
// 这里单独加载store，和在组件中this.$store一个东西
import store from '@/store/';
import JSONBig from 'json-bigint';
import router from '@/router'
import {Toast} from 'vant'

const refreshTokenReq = axios.create({
  baseURL: process.env.NODE_ENV === 'production' ? 'http://ttapi.research.itcast.cn': 'http://ttapi.research.itcast.cn',
  "Content-Type":"application/json",
})

const instance = axios.create({
  // 用来区分生产还是开发环境：process.env.NODE_ENV
  // 生产环境走baseURL，开发环境走代理
  baseURL: process.env.NODE_ENV === 'production' ? 'http://ttapi.research.itcast.cn': 'http://ttapi.research.itcast.cn', 
  // timeout: 5000,
  "Content-Type":"application/json",
  // 处理后端返回数据中的大数字问题
  transformResponse:[function (data) {
    // 后端返回的数据可能不是JSON格式字符串
    // 如果不是的话，那么JSONbig.parse调用就会报错
    // 所以我们使用 try-catch来捕获异常，处理异常的发生
    try {
      // 如果转换成功，则直接把结果返回
      return JSONBig.parse(data);
    } catch (error) {
      // 如果转换失败了，则进入这里
      // 我们在这里把数据原封不动的直接返回给请求使用
      return data
    }
  }]

  // axios默认在内部使用 JSON.parse来转换处理原始数据
  // return JSON.parse(data)
});

// 添加请求拦截器
instance.interceptors.request.use(function (config) {
  const {user} = store.state;
  if (user) {
    config.headers.Authorization = `Bearer ${store.state.user.token}`;
  }
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 响应成功进入这里
  return response;
  // let data = response.data;
  // if (data.resultCode == 416) {
  //   // 证明需要登录
  //   Dialog.alert({
  //     title:"提示",
  //     message: "请登录",
  //     theme: "round-button"
  //   }).then(()=> {
  //     // 点击了确定，则跳到登录页
  //     router.push('/login');
  //   });

  // }
  // return data;
}, async function (error) {
  // 对响应错误做点什么
  // Dialog.alert({
  //   title: "提示",
  //   message: "系统繁忙",
  //   theme: "round-button"
  // })

  // 超过2xx的状态码都会进入到这里
  const status = error.response.status;
  if (status === 400) {
    // 客户端请求参数错误
    Toast.fail("客户端请求参数异常")
  }
  else if (status === 401) {
    // token无效
    // 如果没有user 或者 user.token, 直接去登陆
    const {user} = store.state
    if (!user || !user.token) {
      return redirectLogin()
    }

    // 使用refresh_token,则请求获取新的token
    try {
      const {data} = await refreshTokenReq({
        method: "PUT",
        url:"/app/v1_0/authorizations",
        headers: {
          Authorization: `Bearer ${user.refresh_token}`
        }
      })
      // 拿到新的token之后把它更新到容器中
      user.token = data.data.token
      store.commit('setUser',user)
      // 把失败的请求重新发出去
      // 这请求是request
      return request(error.config)

    } catch (error) {
      // 刷新token失败，直接跳转登录页
      redirectLogin()
    }
    // 拿到新的token之后把它更新到容器中
    // 把失败的请求重新发出去

  } else if (status === 403) {
    // 没有权限操作
    Toast.fail("没有权限操作")
  } else if (status >= 500) {
    // 服务端异常
    Toast.fail("服务端异常，请稍后重试")
  }
  // 抛出异常
  return Promise.reject(error);

  // if (error.response && error.response.status === 401) {
  //   // 校验是否有 refresh_token
  //   const user = store.state.user;
  //   if (!user || !user.refresh_token) {
  //     redirectLogin()
  //     return 
  //   }
  //   // 如果有refresh_token,则请求获取新的token
  //   try {
  //     const res = await axios({
  //       method: 'PUT',
  //       url: 'http://ttapi.research.itcast.cn/app/v1_0/authorizations',
  //       headers: {
  //         Authorization: `Bearer ${user.refresh_token}`
  //       }
  //     })

  //     // 如果获取成功，则把新的token更新到容器中
  //     store.commit('setUser', {
  //       ...user,
  //       token: res.data.data.token  //最新获取的可用的token
  //     })

  //     // 把之前失败的用户请求继续发出去
  //     // config是一个对象，其中包含本次失败请求相关的那些配置信息，例如url、method都有
  //     // return 把request的请求结果继续返回给发请求的具体位置
  //     return request(error.config);

  //   } catch (error) {
  //     // 如果获取失败，直接跳转 登录页
  //     console.log("请求刷新 token 失败",error);
  //     redirectLogin()
  //   }
  // } else if (error.response.status === 500) {
  //   Notify('服务器异常，请稍后重试');
  // }
  // return Promise.reject(error);
});

function redirectLogin() {
  router.push({
    path: '/login',
    query: {
      redirect: router.currentRoute.fullPath
    }
  })

  // router.replace({
  //   path: "/login",
  //   name: "Login",
  //   // 传递查询参数,查询参数会以 ？作为分隔符放到url后面
  //   query: {
  //     // 数据名是自己起的
  //     // 当前路由路径 router.currentRoute 和我们在组件中回去的this.$route是一个东西
  //     redirect: router.currentRoute.fullPath
  //   }
  // })

  // router.push({
  //   name: 'Login',
  //   query: {
  //     redirect: router.currentRoute.fullPath
  //   }
  // })
}

// 导出
export default instance; 
